// Copyright © SixtyFPS GmbH <info@slint.dev>
// SPDX-License-Identifier: MIT

import { MaterialStyleMetrics } from "../styling/material_style_metrics.slint";
import { MaterialPalette } from "../styling/material_palette.slint";
import { MaterialAnimations } from "../styling/material_animations.slint";
import { Icons } from "../icons/icons.slint";
import { ListTile } from "./list.slint";
import { StateLayerArea } from "./state_layer.slint";
import { Icon } from "./icon.slint";

export enum CheckState {
    unchecked,
    partially_checked,
    checked,
}

export component CheckBox {

    in_out property <CheckState> check_state;
    in_out property <bool> tristate;
    in property <bool> has_error;
    in property <bool> enabled <=> state_area.enabled;

    property <bool> checked: root.check_state == CheckState.checked || root.check_state == CheckState.partially_checked;

    callback checked_state_changed(check_state: CheckState);

    min_width: MaterialStyleMetrics.size_48;
    min_height: self.min_width;
    accessible-enabled: root.enabled;
    accessible-checkable: true;
    accessible-checked <=> root.checked;
    accessible-role: checkbox;
    accessible-action-default => { state_area.clicked(); }
    forward_focus: state_area;

    init() => {
        // Initialize tristate as well
        if self.check_state == CheckState.partially-checked {
            root.tristate = true;
        }
    }

    state_area := StateLayerArea {
        width: 100%;
        height: 100%;
        border_radius: max(self.width, self.height) / 2;
        color: MaterialPalette.on_surface;

        background_layer := Rectangle {
            width: MaterialStyleMetrics.size_18;
            height: self.width;
            border_radius: MaterialStyleMetrics.border_radius_2;
            border_width: root.checked ? 0 : 2px;
            border_color: root.has_error ? MaterialPalette.error : MaterialPalette.on_surface_variant;

            if root.checked : Icon {
                colorize: MaterialPalette.on_primary;
                source: Icons.check;

                states [
                    partial_checked when root.check_state == CheckState.partially-checked : {
                        source: Icons.remove;
                    }
                ]
            }

             animate background, border_width {
                duration: MaterialAnimations.opacity_duration;
                easing: MaterialAnimations.opacity_easing;
             }
        }

        clicked => {
            root.toggle();
        }
    }

    changed check_state => {
        if self.check_state == CheckState.partially-checked {
            root.tristate = true;
        }
        root.checked_state_changed(root.check_state);
    }

    public function toggle() {
        if !root.tristate {
            root.check_state = root.check_state != CheckState.checked ? CheckState.checked : CheckState.unchecked;
            return;
        }

        root.check_state = root.check_state == CheckState.checked ? CheckState.partially_checked :
            root.check_state == CheckState.partially_checked ? CheckState.unchecked : CheckState.checked;
    }

    // Keep for backward compatibility
    public function set_check_state(check_state: CheckState) {
        root.check_state = check_state;
    }

    states [
        disabled when !root.enabled : {
           state_area.display_background: false;
           background_layer.border_color: root.checked ? transparent : MaterialPalette.on_surface.with_alpha(38%);
           background_layer.background: root.checked ? MaterialPalette.on_surface.with_alpha(38%) : transparent;
        }
        checked when root.checked : {
            background_layer.border_width: 0;
            background_layer.background: root.has_error ? MaterialPalette.error :  MaterialPalette.primary;
            state_area.color: background_layer.background;
        }
    ]
}

export component CheckBoxTile inherits ListTile {
    in_out property <CheckState> check_state <=> check_box.check_state;
    in_out property <bool> tristate <=> check_box.tristate;
    in property <bool> has_error <=> check_box.has_error;

    callback checked_state_changed <=> check_box.checked_state_changed;

    Rectangle {
        horizontal-stretch: 0;

        check_box := CheckBox {
            enabled: root.enabled;
        }
    }

    // When clicked on this, but not on the checkbox
    // apply the click on the checkbox manually
    // So the user can click anywhere in the tile to toggle
    // the checkbox
    clicked => {
        check_box.toggle();
    }

    // Keep function for backward compatibility
    public function set_check_state(check-state: CheckState) {
        check_box.set_check_state(check_state);
    }
}
